/**
 * 
 * @author ZhangHuihua@msn.com
 * @param {Object} opts Several options
 */
(function($){
    $.fn.extend({
        pagination: function(opts){
            var setting = {
                first$:"li.j-first", prev$:"li.j-prev", next$:"li.j-next", last$:"li.j-last", nums$:"li.j-num>a", jumpto$:"li.jumpto",
                pageNumFrag:'<li class="#liClass#"><a href="javascript:;">#pageNum#</a></li>'
            };
            return this.each(function(){
                var $this = $(this);
                var pc = new Pagination(opts);
                var interval = pc.getInterval();
    
                var pageNumFrag = '';
                for (var i=interval.start; i<interval.end;i++){
                    pageNumFrag += setting.pageNumFrag.replaceAll("#pageNum#", i).replaceAll("#liClass#", i==pc.getCurrentPage() ? 'selected j-num' : 'j-num');
                }
                $this.html(DWZ.frag["pagination"].replaceAll("#pageNumFrag#", pageNumFrag).replaceAll("#currentPage#", pc.getCurrentPage()));
    
                var $first = $this.find(setting.first$);
                var $prev = $this.find(setting.prev$);
                var $next = $this.find(setting.next$);
                var $last = $this.find(setting.last$);
                
                if (pc.hasPrev()){
                    $first.add($prev).find(">span").hide();
                    _bindEvent($prev, pc.getCurrentPage()-1, pc.targetType(), pc.rel());
                    _bindEvent($first, 1, pc.targetType(), pc.rel());
                } else {
                    $first.add($prev).addClass("disabled").find(">a").hide();
                }
                
                if (pc.hasNext()) {
                    $next.add($last).find(">span").hide();
                    _bindEvent($next, pc.getCurrentPage()+1, pc.targetType(), pc.rel());
                    _bindEvent($last, pc.numPages(), pc.targetType(), pc.rel());
                } else {
                    $next.add($last).addClass("disabled").find(">a").hide();
                }
    
                $this.find(setting.nums$).each(function(i){
                    _bindEvent($(this), i+interval.start, pc.targetType(), pc.rel());
                });
                $this.find(setting.jumpto$).each(function(){
                    var $this = $(this);
                    var $inputBox = $this.find(":text");
                    var $button = $this.find(".goto");
                    $button.click(function(event){
                        var pageNum = $inputBox.val();
                        if (pageNum && pageNum.isPositiveInteger()) {
                            dwzPageBreak({targetType:pc.targetType(), rel:pc.rel(), data: {pageNum:pageNum}});
                        }
                    });
                    $inputBox.keyup(function(event){
                        if (event.keyCode == DWZ.keyCode.ENTER) $button.click();
                    });
                });
            });
            
            function _bindEvent($target, pageNum, targetType, rel){
                $target.bind("click", {pageNum:pageNum}, function(event){
                    dwzPageBreak({targetType:targetType, rel:rel, data:{pageNum:event.data.pageNum}});
                    event.preventDefault();
                });
            }
        },
        
        orderBy: function(options){
            var op = $.extend({ targetType:"navTab", rel:"", asc:"asc", desc:"desc"}, options);
            return this.each(function(){
                var $this = $(this).css({cursor:"pointer"}).click(function(){
                    var orderField = $this.attr("orderField");
                    var orderDirection = $this.hasClass(op.asc) ? op.desc : op.asc;
                    dwzPageBreak({targetType:op.targetType, rel:op.rel, data:{orderField: orderField, orderDirection: orderDirection}});
                });
            });
        },
        pagerForm: function(options){
            var op = $.extend({pagerForm$:"#pagerForm", parentBox:document}, options);
            var frag = '<input type="hidden" name="#name#" value="#value#" />';
            return this.each(function(){
                var $searchForm = $(this), $pagerForm = $(op.pagerForm$, op.parentBox);
                var actionUrl = $pagerForm.attr("action").replaceAll("#rel#", $searchForm.attr("action"));
                $pagerForm.attr("action", actionUrl);
                $searchForm.find(":input").each(function(){
                    var $input = $(this), name = $input.attr("name");
                    if (name && (!$input.is(":checkbox,:radio") || $input.is(":checked"))){
                        if ($pagerForm.find(":input[name='"+name+"']").length == 0) {
                            var inputFrag = frag.replaceAll("#name#", name).replaceAll("#value#", $input.val());
                            $pagerForm.append(inputFrag);
                        }
                    }
                });
            });
        }
    });
    
    var Pagination = function(opts) {
        this.opts = $.extend({
            targetType:"navTab",    // navTab, dialog
            rel:"", //用于局部刷新div id号
            totalCount:0,
            numPerPage:10,
            pageNumShown:10,
            currentPage:1,
            callback:function(){return false;}
        }, opts);
    }
    
    $.extend(Pagination.prototype, {
        targetType:function(){return this.opts.targetType},
        rel:function(){return this.opts.rel},
        numPages:function() {
            return Math.ceil(this.opts.totalCount/this.opts.numPerPage);
        },
        getInterval:function(){
            var ne_half = Math.ceil(this.opts.pageNumShown/2);
            var np = this.numPages();
            var upper_limit = np - this.opts.pageNumShown;
            var start = this.getCurrentPage() > ne_half ? Math.max( Math.min(this.getCurrentPage() - ne_half, upper_limit), 0 ) : 0;
            var end = this.getCurrentPage() > ne_half ? Math.min(this.getCurrentPage()+ne_half, np) : Math.min(this.opts.pageNumShown, np);
            return {start:start+1, end:end+1};
        },
        getCurrentPage:function(){
            var currentPage = parseInt(this.opts.currentPage);
            if (isNaN(currentPage)) return 1;
            return currentPage;
        },
        hasPrev:function(){
            return this.getCurrentPage() > 1;
        },
        hasNext:function(){
            return this.getCurrentPage() < this.numPages();
        }
    });
})(jQuery);
